%\begin{Implementation}

\setcounter{section}{0}

\section{Introducció}

Podem separar la implementació d'aquest projecte en dos grans blocs conceptuals:

\begin{enumerate}
\item Eixamplar la biblioteca de mapes

      \begin{enumerate}
      \item En primer lloc la implementació i integració dels mòduls de GML i KML en la biblioteca mapsforge.
      \item També portar la habilitat de escriure mapes directament al dispositiu, cosa que requeria portar Osmosis a Android (mapfile-writer4and).
      \item I finalment la implementació de la façana de SL4A.
      \end{enumerate}

\item En segon lloc la integració de les biblioteques modificades en el projecte ZamiaDroid a nivell de demostració funcional.
      
      \begin{enumerate}
      \item Crear l'aplicació autònoma de visualització de mapes (erdapfel) i implementar-hi els mètodes de comunicació dissenyats.
      \item Modificar el Zamia per assolir la comunicació bidireccional amb l'aplicació creada.
      \end{enumerate}
\end{enumerate}

Cadascun d'aquests blocs ha tingut les seves particularitats i entorns de desenvolupament diferents, tal i com s'ha esmentat anteriorment, i a continuació es poden veure els detalls d'implementació més rellevants de cadascun.

\section{Biblioteca de mapes}

\subsection{Problemàtica amb JiBX}

Abans d'entrar en detalls sobre la implementació de les extensions de la biblioteca mapsforge per a KML i GML, deixeu-me comentar alguns problemes sorgits de la utilització de la implementació/utilització de JiBX.

\paragraph{}

El projecte JiBX proporciona un mètode automàtic per a generar classes Java a partir d'un esquema XML (codegen). Després d'això cal decorar aquestes classes ja compilades (en un procés anomenat bytecode enhancement) mitjançant un component anomenat ``binding compiler'', que llegeix un fitxer (definició del binding) on està estipulada com s'ha de fer la conversió de document XML a classe de Java. Aquest pas es necessari per tal que en temps d'execució JiBX sàpiga on posar cada element del fitxer a parsejar. Un cop seguits aquests passos ja es pot fer servir la biblioteca run-time de JiBX per convertir dinàmicament un fitxer que compleixi l'esquema en instàncies d'aquest conjunt de classes, i treballar amb elles.

\paragraph{}

La primera fase del procés per poder gaudir dels avantatges que brinda parsejar documents XML amb JiBX, doncs, és fer servir aquest mètode automàtic (codegen) que genera tant les classes d'objectes Java com el fitxer de definició de binding per continuar el procés.

\paragraph{}

Desgraciadament, el mètode automàtic de generació de codi que s'havia provat satisfactòriament durant l'anàlisi de JiBX (amb la versió 2.1 de l'esquema de kml) no funcionava per als esquemes de la versió ``oficial'' de kml, la versió 2.2 de opengis. 

\paragraph{}

Després d'intentar arreglar els problemes i contactar amb la comunitat de JiBX sense èxit (podeu trobar més detalls a l'\hyperlink{annex-email-list-jibx}{annex corresponent}) es va optar per crear manualment un binding i utilitzar una jerarquia de classes de la versió 2.1.

\paragraph{}

El fitxer de definició de binding a més a més, és molt complex i te una gran varietat d'opcions i possibilitats, i la versió que es va fer manualment segurament no aprofita totes les capacitats de JiBX.

\paragraph{}

A més, degut a la complexitat d'elaboració d'aquests fitxers no es va aconseguir fer que diferents esquemes de KML convergissin en les mateixes classes generades, obligant a crear una classe abstracta en les biblioteques esteses de mapsforge, que finalment s'especifiqui en cadascuna de les versions dels esquemes KML que es vulguin implementar/suportar (com es pot veure aquí \autoref{fig-KMLBinding-class-diagram}).

\paragraph{}

Tot això pot suposar que el parser sigui inestable per algunes determinades instàncies de fitxers KML, ja que no es garanteix la completa compatibilitat entre versions dels esquemes, ni que el procés de binding sigui prou robust com per tractar qualsevol eventualitat que es pugui torbar en un fitxer kml.

S'ha comprovat/garantit que tant els fitxers kml descarregats de google maps, com els fitxers generats per ZamiaDroid sigui acceptats sense problema, però no es descarta que en altres casos s'interpreti com a mal format un fitxer que teòricament compleix l'esquema de KML.

\paragraph{}

Un inconvenient semblant va succeir amb els esquemes de GML.

\paragraph{}

Aquest inconvenient es va detectar molt tard en el procés, i l'única alternativa viable en aquell moment va ser aquesta.

\paragraph{}

De tenir més temps, o un coneixement/suport més extens de la biblioteca JiBX, segurament es podria arreglar aquest problema i evitar errors d'execució.

\paragraph{}

També s'hauria pogut abandonar el suport de JiBX i implementar un parser SAX senzill, adaptat només per a les necessitats concretes d'aquest projecte. Però es va preferir mantenir JiBX i deixar com a treball futur la optimització del binding de JiBX.

\subsection{Mapsforge-GML-KML}

La arquitectura de mapsforge ja estava predefinida, i per tant no es podia modificar completament.

 \paragraph{}

En aquesta secció parlaré exclusivament de la implementació dels mòduls de GML/KML propis i no de la implementació de la biblioteca mapsforge, informació sobre la implementació i altre documentació tècnica d'aquesta biblioteca es pot trobar aquí\cite{bib-mapsforge}.

 \paragraph{}

La manera menys invasiva que es va trobar per a afegir suport de KML i GML va ser crear una nova classe Overlay que permetes llegir fitxers d'aquest tipus, i generes les característiques contingudes en ells amb els Overlays ja existents per defecte a la biblioteca. És a dir una classe que contingues totes les capes representables del fitxer GML/KML i també els mètodes per tractar-les.

 \paragraph{}

Una alternativa hagués estat modificar la classe MapView i permetre que de la mateixa manera que es creen mapes a partir de fitxers .map en el mètode setMapFile ``entengués'' també els fitxers KML i GML.

 \paragraph{}

Això tenia però alguns inconvenients.

 \paragraph{}

Per començar significaria canviar la manera com actualment es carreguen els fitxers de mapes, ja que ara mateix la carrega d'un fitxer implica la substitució completa d'un mapa per un altre, i no existeix la possibilitat de sobreposar les capes del mapa carregat actualment amb les del nou fitxer a carregar.

 \paragraph{}

Aquest és un canvi que podria suposar poc important. Però si tenim en compte que la posició de la comunitat de mapsforge pel que s'entén de la proposta inicial en referència a la inclusió de KML, aquesta funcionalitat no es veu tan pràctica per a carregar mapes complets en aquests formats (cosa que també seria possible) sinó com a una manera de incloure dades addicionals als mapes ja existents.

 \paragraph{}

És a dir, que l'escenari pel qual la comunitat de mapsforge veu més útil aquesta nova característica és el d'afegir informació, per exemple rutes o punts d'interès exportats des de google maps, o google earth, o qualsevol altre programa que permeti exportar a KML o GML.

 \paragraph{}

En altres paraules, que la utilitat més gran que es veu a la addició del suport per a fitxers KML i GML és poder estandarditzar la manera com es gestionen aquests fitxers, que d'altra banda s'hauria de fer el desenvolupador final, amb el risc i les inconveniències que això comporta, i la poca eficiència d'haver de reescriure codis tant similars tantes vegades.

 \paragraph{}

És per això que semblava més bona idea no haver de modificar la manera com ara mateix estan definides les interfícies per a la càrrega de fitxers de mapes que ara existeixen, afegint la possibilitat de un ``append'' per entendre'ns.

 \paragraph{}

I en darrer lloc aquesta estratègia hagués implicat una modificació important de la classe MapView, que és una classe molt important i que encara esta en constant desenvolupament per la comunitat de mapsforge, cosa que hagués dificultat molt la coordinació entre el desenvolupament dels mòduls GML/KML de la manera com s'havia plantejat.

 \paragraph{}

Així que es va creure que la millor manera era crear Overlays capaços d'acceptar com a entrada fitxers KML o GML i generar-ne les característiques internament.

\subsubsection{KMLBinding.java}

Aquesta és una classe abstracta que representa una vinculació concreta de JiBX. Ha de ser implementada en alguna classe que accepti un xml schema de KML concret, i proporcionarà mètodes per parsejar fitxers KML vàlids i obtenir l'equivalent en Overlays de les seves ``features''.

\paragraph{}

Les classes que heretin de KMLBinding i implementin un esquema concret importaran les classes de Java generades gràcies al Procés previ de vinculació i generació de codi amb JiBX.

\paragraph{}

Així en el moment requerit faran ús dels mètodes d'unmarshall de la biblioteca jibx-run (la petita biblioteca que en temps d'execució parseja els fitxers a objectes Java) ja podem treballar amb la representació del fitxer en forma d'instàncies de classes Java.

\paragraph{}

El mètode més rellevant de la classe és parseKML, que s'encarrega de fer aquesta crida i a continuació processar els objectes Java obtinguts.

\paragraph{}

És en aquest moment on es fa la ``transformació'' de les característiques (``features'') de KML a els Overlays més apropiats de que disposem.

\paragraph{}

Així aquesta ``transformació'' agafa les característiques especificades al fitxer KML i, depenent del seu tipus genera Overlays amb característiques equivalents.

\paragraph{}

Actualment es tracten degudament els elements geomètrics poligonals, els camins i els punts, que són ``transformats'' als Overlays de mapsforge de OverlayWay amb emplenat intern, OverlayWay sense emplenat i KMLOverlayItem respectivament.

\paragraph{}

Els dos esquemes de KML que s'han vinculat amb JiBX, i que per tant la biblioteca pot interpretar són el de Google i el d'opengis.

\begin{figure}
        \centering
                \includegraphics[width=0.8\textwidth]{misc/KMLBindingClassDiagram.eps}
        \caption{Diagrama de classes de KMLBinding i els seus hereus.}\label{fig-KMLBinding-class-diagram}
\end{figure}

\FloatBarrier
\subsubsection{KMLLayer.java}

La classe KMLLayer mimetitza l'estructura d'OverlayList, ja que en el fons també és una llista heterogènia d'Overlays que implementa les interfícies Java de RandomAccess i de List.

\paragraph{}

En essència consisteix en una llista d'objectes de la classe abstracta Overlay amb tots el mètodes necessaris per garantir la implementació de les dos interfícies Java anteriorment mencionades i també una instància de la classe KMLBinding, que és una instància que representa una vinculació concreta de JiBX, i que conté una sèrie de mètodes per parsejar fitxers KML (en aquest cas concret).

\paragraph{}

Fent servir aquest mètodes del KMLBinding es poden obtenir les Overlays que conté el fitxer KML, i afegir-los a la llista que aquesta classe manté.

\paragraph{}

Aquesta classe no és ``thread-safe'' i se suposa que serà inclosa a la llista d'Overlays del mapView o en algun altre contenidor que n'asseguri el tractament com es degut durant el cicle de vida de l'aplicació.

%\paragraph{}

%Mentre es desenvolupaven aquests mòduls la API dels Overlays va ser millorada paral·lelament per la comunitat de mapsforge.

\subsubsection{GMLOverlay.java}

La idea de GMLOverlay era inicialment la mateixa que per a KMLOverlay.

\subsection{mapfile-writer4and}

\hypertarget{implm-mapfile-writer}{}Mapfile-writer4and és la combinació del port de l'eina osmosis a Android i del mòdul d'osmosis mapfile-writer, que forma part de mapsforge.

La totalitat del codi que es volia ``portar'' era codi Java amb interfície de línia de comandes (sense GUI), així que semblava factible adaptar-ho a l'entorn Android, compilar-ho i distribuir-ho com a un paquet normal.

\paragraph{}
Llavors la comunicació entre les aplicacions que en volguessin fer ús i el mapfile-writer4and hauria de ser efectuada mitjançant intents com de costum en Android.

\paragraph{}
El procés de desenvolupament de mapfile-writer4and constava, doncs, de les següents parts en teoria: 

\begin{itemize}
        \item La adaptació d'Osmosis per a la plataforma Android
        \item La adaptació del mòdul de mapsforge
        \item La creació d'una aplicació d'Android
\end{itemize}

Abans de començar, però, vaig enviar un missatge a la llista de correu dels desenvolupadors d'osmosis (osmosis-dev) per saber si s'havia intentat abans realitzar aquest port, o si existia algun impediment de base que fes que es tractés d'una tasca inviable, i al veure que no era així, vaig començar. 

Aquests són algunes de les dificultats tècniques van sorgir durant el procés. A continuació esmento les més importants:

\subsubsection[Problemes del dex]{Conversion to Dalvik format failed: Unable to execute dex: Java heap space}

Per tal d'aconseguir el mapfile-writer4and, el primer que es va intentar va ser utilitzar l'eina osmosis sense cap modificació ni adaptació.

\paragraph{}
Per tant el primer que es va fer va ser crear una aplicació d'Android que inclogués l'eina osmosis i tots els seus mòduls descarregats directament de la pàgina del projecte.

\paragraph{}
Aquesta aplicació d'Android havia de permetre l'execució mitjançant intents, i també es va pensar de proporcionar-li una petita interfície gràfica pel cas de que es volgués executar com a ``stand-alone''.

\paragraph{}
Per aconseguir-ho el que calia fer en la activitat principal (i única) de l'aplicació era comprovar si s'havia invocat amb paràmetres des d'un intent (en cas de que fos així s'esperava tenir un paràmetre a ``extras'' que fos l'argument de línia de comandes per a l'eina osmosis) i en cas de que no fos així mostrar una simple interfície on es podia introduir aquests arguments i executar-los. 

\paragraph{}
En ambdós casos, el que es feia era cridar a la classe principal d'osmosis (inclosa al projecte en forma de jar) amb un ``execute'', amb aquests arguments.

\paragraph{}
Però naturalment aquesta aproximació tant directa no va funcionar, posant de manifest que seria necessària una adaptació d'osmosis per a la plataforma Android. 

\paragraph{}
De fet el primer problema que vaig trobar va resultar ser un problema de l'entorn de desenvolupament i no pas un problema conceptual o de procediment.

\paragraph{}
L'error ``Conversion to Dalvik format failed: Unable to execute dex: Java heap space'' era degut (en aquest cas) a una configuració errònia de l'eclipse (i al meu entendre a una implementació no gaire eficient del compilador dex per Android).

\paragraph{}
El problema era que la memòria de la màquina virtual de Java assignada a l'eclipse mateix s'esgotava quan es volien processar una gran quantitat de paquets jar per incloure al projecte.

\paragraph{}
D'alguna manera el consum de memòria es disparava de manera gairebé exponencial per cada nou jar que s'afegia al projecte, i el fet que inicialment s'intentessin incloure tots els mòduls d'osmosis al projecte resultava ser massa (encara que el conjunt de biblioteques ``només'' pesés uns 8Mb).

\paragraph{}
Per tal de solucionar aquest error es va incrementar la memòria de que disposava l'eclipse mitjançant la modificació d'un fitxer de configuració, i també es van eliminar mòduls innecessaris d'osmosis del projecte.

\subsubsection[Problemes del JPF]{``No validating SAXParser implementation available''}

Després d'això, un dels problemes més importants que van sorgir va ser un error d'execució de l'Osmosis en la plataforma Android, que es queixava de la manca de un parser SAX a l'entorn d'execució \emph{``No validating SAXParser implementation available''} quan osmosis intentava llegir el fitxer de configuració plugin.xml. 

\paragraph{}
Això molt probablement fos degut a que l'entorn d'execució d'Android, tot i ser una màquina virtual de Java, té algunes particularitats, i li manquen alguns elements estàndard.

\paragraph{}
Per tal de solucionar aquest problema la ajuda de la comunitat osmosis-dev va ser molt valuosa.

\paragraph{}
Un dels membres d'aquesta comunitat em va comentar que aquest error succeïa en un estadi on l'aplicació intentava cercar els plugins presents en el sistema per configurar-se. I també em va fer saber que hi havia diversos mecanismes per a poder dir a osmosis quins plugins existien en el sistema, i el mètode que provocava aquest error era l'ús de JPF (Java Plugin Framework). També em va comentar que el JPF no era ni tan sols el mètode més emprat.

\paragraph{}
El fet que osmosis permetés altres maneres de carregar plugins que no fos amb aquest fitxer xml obria la porta a l'opció de modificar osmosis perquè prescindís completament de JPF i d'aquest mecanisme.

\paragraph{}
Així es va descarregar el codi font d'osmosis i modificar perquè no utilitzés el sistema de gestió de plugins JPF.

\paragraph{}
Aquesta versió ``capada'' d'osmosis requeria la configuració ``manual'' dels plugins.

\paragraph{}
Això és va aprofitar per fer una tria dels plugins que eren estrictament necessaris per proporcionar les funcionalitats que requeria la nostre biblioteca, i prescindir de la resta.

\paragraph{}
Els mòduls que es van conservar van ser els que permeten la lectura de fitxers binaris d'OpenStreetMap (.pbf), els que permeten la lectura de fitxers XML d'OpenStreetMap (.osm), així com alguns plugins auxiliars d'aquests dos mòduls, i evidentment el mòdul de mapsforge-map-writer (que permet escriure el fitxer .map).

\paragraph{}
Aquest procés de purga de mòduls va ajudar també a solucionar l'error anterior de manera definitiva.

\subsubsection{OutOfMemoryError}

Un cop adaptat osmosis per a Android i configurats els plugins correctament l'aplicació mapfile-writer4and ja estava preparada, i va ser provada satisfactòriament a l'emulador d'Android, i encara que evidenciava que era un procés lent, funcionava correctament.

\paragraph{}
Però per desgràcia, al provar aquesta funcionalitat en el meu telèfon de proves més endavant (en aquell moment un HTC magic) va sorgir un lleig error en temps d'execució que es queixava de que la memòria per a la pila de Java s'havia esgotat i no era possible generar el fitxer.

\paragraph{}
En el cas de dispositius més potents on es va provar aquesta aplicació (com el Nexus 7), el procés s'executava satisfactòriament.

\paragraph{}
El problema en els dispositius més antics i/o limitats, era que la memòria que el Dalvik proporcionava per a la pila no era suficient per executar el mòdul mapsforge-map-writer.

\paragraph{}
El procés per generar un mapa de mida petita amb osmosis+mapsforge-map-writer consumeix aproximadament 90Mb. 

\paragraph{}
La mida de la pila de Java d'Android varia molt segons el dispositiu, però, per exemple en el cas d'un telèfon de gamma mitjana/baixa sol ser de l'ordre de 64Mb mentre que en el d'una tauleta de gamma alta pot ser de 128Mb o 256Mb. En un dispositiu com l'HTC magic, que ja es força antic, aquesta memòria és de tan sols 24Mb.

\paragraph{}
Està clar, doncs, que aquest error era molt preocupant i desagradable, ja que limitava molt la utilització d'aquesta funcionalitat de la biblioteca. Per això es va dedicar un temps considerable a cercar possibles solucions al respecte\cite{bib-android-memory}\cite{bib-osmosis-man}. Tant per intentar optimitzar osmosis o mapsforge-map-writer, com per intentar expandir la memòria de la pila de Java als dispositiu.

\paragraph{}
Els resultats d'aquesta recerca van ser decebedors.

\paragraph{}
En primer lloc es va comprovar que malgrat que el dispositiu pogués tenir suficient memòria física per executar la tasca, degut al restringit entorn de la màquina virtual de Java que és el Dalvik resultava impossible incrementar la memòria de que disposava una aplicació Android.

\paragraph{}
També es va veure que osmosis i el mòdul mapsforge-map-writer (que és el pas que, de fet, esgotava la memòria) no podia ser optimitzat per consumir menys recursos, ja que això anava en contra dels principis de disseny del mòdul mateix, que prioritzava un alt consum de recursos per proporcionar un baix temps d'execució (cal recordar que aquest mòdul va ser dissenyat tenint en ment la seva execució en un servidor). A l'\hyperlink{annex-email-list-mapsforge-2}{annex} podeu trobar més informació.

\paragraph{}
Sembla a ser que si es prescindeix del Dalvik (per exemple fent servir l'NDK) és possible aprofitar més la memòria del dispositiu sense restriccions, però portar osmosis i el mòdul mapsforge-map-writer (escrits en Java) al llenguatge natiu de l'NDK (C o C++) es va descartar per ser inviable. També es va descartar reescriure el mòdul d'escriptura de fitxers .map per fer-lo més ``eficient'' però lent, ja que es va creure que es desviava molt del marc del projecte i no interessava al projecte mapsforge.

\paragraph{}
Així que malgrat els esforços per portar osmosis a Android, i malgrat també el relatiu èxit en aquesta empresa (osmosis i la majoria dels seus mòduls podien ser executats sense inconvenient), al final va resultar poc útil, ja que només dispositius de segment elevat són capaços d'executar aquesta tasca al dispositiu mateix.

\paragraph{}
La resta d'usuaris han de processar els mapes en un ordinador personal o descarregar-los d'algun servidor. Cosa que no resulta ideal (però recordem que és el ``modus operandi'' d'altres opcions, com ara OsmAnd).


\subsection{SL4A Facade}

L'arquitectura de SL4A ja ha estat explicada anteriorment (\autoref{fig-arquitectura-sl4a}). Segons aquesta arquitectura, per poder afegir suport per a una ``nova'' biblioteca de Java calia modificar el codi de SL4A (ja que no es preveia cap mecanisme dinàmic per afegir noves façanes). Concretament el que cal fer és un nou projecte façana amb una classe que hereti de ``RpcReceiver'', i allà posar-hi els mètodes que es volen ``publicar''. I modificar la classe FacadeConfiguration del nucli de SL4A perquè sàpiga de l'existència d'aquesta nova façana. 

\paragraph{}
Fent això, en el moment que un dels llenguatges d'scripting cridi a la ``nostra'' funció, la crida s'interceptarà i s'executarà el codi que hàgim implementat a la façana seguint el mecanisme convencional de SL4A.

\paragraph{}
Així les classes que s'han implementat o modificat són aquestes:

\begin{enumerate}
\item \emph{com.googlecode.android\_scripting.facade.MapsforgeFacade.java} dins del projecte MapsforgeFacade, que serà la nova façana encarregada de comunicar-se amb la biblioteca de mapes.
\item \emph{com.googlecode.android\_scripting.facade.FacadeConfiguration.java} dins del projecte ScriptingLayer, que és el projecte ``principal'' del codi font de SL4A, i cal ser modificada per afegir la façana creada i que el sistema la reconegui.
\end{enumerate}

La creació del nou projecte de Java que conté la façana no te cap particularitat (només calia tenir en compte el nom del paquet fos \emph{com.\-googlecode.\-android\_scripting.\-facade}. La implementació d'aquesta classe senzillament proporciona un mètode showMapsforgeMap, que espera tres cadenes de caràcters com a paràmetres, i fa una crida a erdapfel amb els mateixos arguments que acceptaria la invocació de l'intent, i que estan especificats \hyperlink{implm-erdapfel-intent-args}{aquí}, i que són opcionals.

\paragraph{}
Com s'ha comentat abans, la utilització d'erdapfel com a punt d'entrada de la façana SL4A es va decidir per tal d'evitar afegir les biblioteques esteses de mapsforge coma dependència de SL4A, cosa que no tenia massa sentit.

\paragraph{}
Això, però, força a que per fer servir aquesta funcionalitat és necessari instal·lar erdapfel (a meś de la versió ``modificada'' de SL4A).

\paragraph{}
Tot plegat fa que ara mateix aquesta sigui més aviat una implementació ``experimental'', encara que funcional.

\section{Integració amb ZamiaDroid}

Per a la integració amb ZamiaDroid calia fer unes quantes modificacions a Zamia i també crear l'aplicació de visualització de mapes erdapfel.

\paragraph{}
En primer lloc es comentaran les modificacions a Zamia, i posteriorment es detallaran els apartats de desenvolupament d'erdapfel més interessants.

\subsection{Modificacions a ZamiaDroid}

Tal i com s'ha explicat a l'apartat d'anàlisi i disseny, s'ha procurat haver de modificar el mínim possible el ZamiaDroid.

\paragraph{}
Malgrat això, algunes modificacions han estat indispensables per poder permetre l'ús de les biblioteques esteses de mapsforge (a través d'erdapfel).

\paragraph{}
Per realitzar aquestes modificacions s'ha comptat amb la inestimable ajuda de David Martí Pino, el principal desenvolupador i creador de ZamiaDroid.

\paragraph{}
A part d'afegir la invocació d'erdapfel mitjançant intents des de Zamia (la modificació més senzilla d'entendre), ha calgut fer un parell d'altres coses, una mica menys evidents.

\paragraph{}
Ara les esmentaré, i més endavant, a l'apartat d'erdapfel s'acabarà de veure clar la seva raó de ser.

\subsubsection[Modificacions als KML]{Afegir referències als fitxers KML generats}

Per tal de poder referenciar els objectes del KML i que el Zamia entengui quin dels objectes ha ``premut'' l'usuari des d'erdapfel, s'ha fet servir el mateix camp ``id'' que totes les ``features'' d'un KML tenen.

\paragraph{}
Aquest és un camp que no es fa servir per la representació visual, i que Zamia tampoc necessitava, així que es va acordar que seria l'identificador de tornada.

\paragraph{}
Aquest identificador no te perquè ser el mateix de la base de dades de Zamia, només ha de ser un paràmetre que el programa hoste (en aquest cas Zamia) sàpiga interpretar inequívocament. 

\subsubsection[Punt d'entrada per a erdapfel]{Afegir un punt d'entrada per a la ``tornada'' des de l'aplicació erdapfel}

També calia preparar ZamiaDroid per a ser ``iniciat'' des d'erdapfel.

\paragraph{}
En aquest cas això va consistir en afegir un ``punt d'entrada'' directament a l'editor de citacions mitjançant un intent.

\paragraph{}
Bàsicament les modificacions a fer al Zamia van ser modificar lleugerament l'Activity de l'editor de citacions perquè pogués ser cridada directament.

\subsection{Erdapfel}

L'aplicació erdapfel consta d'una pantalla (Activity) principal i dues d'auxiliars. La implementació de la Activity de configuració no te massa rellevància, així que no es comentarà, però em sembla interessant comentar alguns detalls de la pantalla selecció de fitxers:

\subsubsection{FilePicker}

Android no disposa d'un navegador de fitxers per defecte, que permeti recórrer la estructura de directoris del sistema. És possible instal·lar aplicacions que proporcionin aquesta funcionalitat, però no sembla haver-hi cap estàndard, ni tan sols estàndard ``de facto''. Així doncs, si una aplicació vol donar la possibilitat de seleccionar fitxers de manera visual, normalment cal que implementi el selector ``manualment''. 

\paragraph{}
És clar doncs que existeixen moltes implementacions doncs per a aquesta funcionalitat, i moltes d'elles de codi obert. En el nostre cas concret, s'ha aprofitat que un dels exemples de mapsforge implementava una interfície similar per adaptar-la a les nostres necessitats i fer-ne ús.

\paragraph{}
Es tracta de la classe filePicker i de les classes fileFilter.

filePicker és una classe que hereta d'Activity i implementa la interfície AdapterView.OnCLickItemListener. 

A grans trets el que fa és mostrar els continguts d'un directori (ja siguin fitxers o carpetes) i permet la navegació per les carpetes i la selecció dels fitxers. 

S'ha modificat, però, perquè només es mostrin els fitxers vàlids que es permet carregar en cada moment gràcies a la utilització de les classes fileFilter.

Així un cop seleccionat un fitxer vàlid, la activitat acaba i publica el resultat fent ús del procediment usual en Android (setResult). 

Com que erdapfel haurà cridat aquesta Activity emprant el mètode ``startActivityForResult'' aquestes dades estaran disponibles per la Activity principal del programa. (aquest és el procediment de comunicació més usual entre Activities en al plataforma Android)

\paragraph{}

També cal dir que els ``recursos gràfics'' per defecte d'Android no disposen de cap representació d'un fitxer o d'una carpeta (almenys a les versions per les quals es pretén donar suport amb erdapfel). Per tant es van haver de manllevar icones adients i empaquetar-les amb l'aplicació. 

Les icones de directoris es van manllevar del Tango desktop project\cite{bib-tango}, ja que es tracta d'un projecte completament Lliure i gratuït, i fa servir estàndards visuals molt estesos i en certa manera intuïtius per als usuaris.

Les icones per als documents que suporta erdapfel són les mateixes que la icona principal del projecte, i va ser dissenyada especialment per a l'ocasió.

\begin{figure}[!ht]
  \centering
        \includegraphics[width=0.8\textwidth]{misc/erdapfel10.eps}
  \caption{Captura d'erdapfel filePicker.}\label{fig-erdapfel10}
\end{figure}

\paragraph{}
La resta de parts interessants de la implementació formen part de la pantalla principal a on es veu el mapa.

\FloatBarrier
\subsubsection{MainActivity}

La activitat principal d'erdapfel és la que mostra el mapa, i es carrega directament al començar l'aplicació.

El primer que comprova aquesta Activity (en el mètode OnCreate) és si ha estat invocada amb paràmetres per carregar directament un fitxer de mapes (KML, GML o map). 

Això ho determina fent una cerca a la estructura d'extres del mateix intent. Aquesta estructura és el sistema usual de passar paràmetres quan s'invoca un intent d'Android, i bàsicament es tracta d'un diccionari clau/valor on es guarden paràmetres que poden ser de tipus simples de Java, o qualsevol classe que implementi la interfície serialitzable. Les claus que es cerquen en aquesta estructura són les següents:

\hypertarget{implm-erdapfel-intent-args}{}
\begin{itemize}
        \item ``MapFile''
        \item ``KMLFile''
%        \item ``GMLFile''
        \item ``KMLCallBackURL''
\end{itemize}


\paragraph{}
La primera clau espera tenir per valor un String que contingui el camí (path) a un fitxer de tipus map, i si al carregar-se l'aplicació es detecta aquesta clau no s'intenta carregar un mapa des d'internet sinó que es carrega directament el mapa indicat.

En cas de que el mapa no es pogués carregar, o senzillament aquesta clau no fos present a la estructura d'extres, es procedeix a intentar descarregar el mapa d'OpenStreetMap generat amb mapnik.


\paragraph{}
La segona clau està emparellada amb un String que representa també una ubicació de fitxer, en aquest cas s'espera un fitxer KML.

\paragraph{}
La distinció entre KML i Map en aquest nivell és conseqüència del tractament dels fitxers KML com a Overlay i no com a format de ``mapa'' tal i com mapsforge ho entén (com es va comentar a l'apartat d'anàlisi i disseny).

Això fa que el tractament per a aquest fitxers sigui molt diferent del dels de mapes. A més aquesta separació té sentit si en un futur es volgués, per exemple, carregar un mapa i al mateix temps afegir-hi una capa des d'un KML. O donar la possibilitat de carregar més d'un KML (en diferents capes) a l'inici de l'aplicació, cosa que no te sentit amb els mapes perquè només es mostraria un sol mapa a cada instant.

\paragraph{}
La tercera clau és completament opcional, però només te sentit la seva presència quan es carrega un fitxer KML. 

Es tracta d'una dada necessària per establir la comunicació entre aplicacions des d'erdapfel cap a la possible aplicació ``mare'' que el vol fer servir com a visor.

El valor d'aquesta clau ha de ser una URI (de fet un String que conté una URI) que especifiqui el ``punt de tornada'' que l'aplicació ``mare'' vol que erdapfel empri.

Això o algun mecanisme similar és necessari per poder establir una comunicació bidireccional entre erdapfel i les aplicacions que el volen usar, tal i com s'ha explicat a l'apartat de disseny (en aquest cas concret es demostra la comunicació amb Zamia, però el mecanisme pot ser estès per a qualsevol possible ``client'').

\paragraph{}
El punt d'entrada a especificar no és altre que el ``nom'' estàndard d'Android per l'intent que es vol executar quan l'usuari interaccioni amb els objectes carregats del KML. En el cas concret de Zamia, per exemple, el punt d'entrada és l'editor de citacions. Així, quan es realitza un ``onTap'' sobre una citació a l'erdapfel, aquest, invoca un intent amb la URI definida i amb els paràmetres de l'objecte del KML que l'usuari ha pitjat. Zamia, al ser cridat mitjançant aquest intent, agafa els paràmetres que li proporciona erdapfel i els interpreta (en aquest cas concret el paràmetre més rellevant és l'identificador de citació), fa una consulta sobre la seva base de dades i mostra l'editor de citacions, de la mateixa manera que ho hauria fet si s'hagués ``pitjat'' una citació des del mapa de google integrat dins de ZamiaDroid.

El fet que Android permeti invocar intents a partir d'una URI d'aplicació facilita que aquest ``punt d'entrada'' pugui ser especificat de manera unívoca, clara i d'una manera acceptada pel sistema Android. 

\paragraph{}
Actualment la càrrega de fitxers GML a l'inici de l'aplicació no està contemplada.

Això es degut a que ZamiaDroid (que és la principal aplicació que fa ús d'aquest ``punt d'entrada'' a erdapfel ara mateix) no requeria aquesta característica, i també perquè en el disseny inicial d'erdapfel no s'especificava aquesta funcionalitat.

Si es volgués implementar tan sols caldria afegir una nova clau que fes possible, o estendre l'ús de la clau ``KMLFile'', encara que això podria portar lloc a confusió.

\subsubsection{Detalls de la interfície principal}

Respecte la pantalla principal comentaré breument com s'han implementat els modes de dibuix de polígons i de mètriques, i com s'interacciona amb les biblioteques esteses de mapsforge, tant per mostrar documents kml o les figures geomètriques, com el mecanisme per generar mapes offline que proporciona mapfile-writer4and.

Abans d'això, però comentaré breument algun detall de la interfície principal que es mostra.

\paragraph{}
Tal i com s'ha dit al capítol d'anàlisi i disseny, es volia que la interfície d'usuari per a la visualització de mapes fos neta i clara, i que els controls no obstruïssin la visió dels mapes.

\paragraph{}
Per assolir això es va optar per fer un ús intensiu del menú desplegable d'Android (OptionsMenu) per a les opcions de carregar capes KML/GML, d'obrir fitxers de mapes locals, guardar mapes offline, exportar les capes dibuixades a KML o accedir a la configuració de l'aplicació. 

\paragraph{}
Això, però, va fer sorgir problemes en les versions més noves d'Android (a partir de la 4) on es ``desencoratja'' l'ús dels botons físics i d'aquest menú en favor de barres d'eines desplegables (action bar). Google recomana als desenvolupadors canviar les seves interfícies considerant aquesta eventualitat, ja que en un futur no garanteix que aplicacions dependents del botó físic de menú siguin acceptades.

Per mantenir el nivell de compatibilitat amb sistemes antics, però es va decidir obviar aquestes recomanacions i solucionar els errors que poguessin aparèixer en versions noves en el moment que aquests errors apareguin.

\paragraph{}
Fent servir aquest ``menú'' d'opcions desplegable ens asseguràvem que la pantalla estava ``neta'' mentre l'usuari consultava el mapa.

Però per a permetre a l'usuari pintar polígons o mesurar distàncies es va voler implementar una solució més accessible i ``dinàmica''. Per això es va intentar imitar els controls de ``zoom'' que mostra el mapa de mapsforge (i el de google), que només apareixen durant un temps limitat després que l'usuari hagi realitzat una acció.

\paragraph{}
Dissortadament degut al fet que per aquesta aplicació s'ha interceptat i ``sobreescit'' el control d'esdeveniments (events), tal i com s'explicarà més endavant amb detall, aquesta ``imitació'' no és perfecte, i a vegades es des-coordina respecte als controls de zoom.

\begin{figure}[!ht]
  \centering
        \includegraphics[width=0.8\textwidth]{misc/erdapfel01.eps}
  \caption{Captura d'erdapfel mainActivity.}\label{fig-erdapfel01}
\end{figure}

\begin{figure}[!ht]
  \centering
        \includegraphics[width=0.8\textwidth]{misc/erdapfel02.eps}
  \caption{Captura d'erdapfel mainActivity amb la ui amagada.}\label{fig-erdapfel02}
\end{figure}

\FloatBarrier
\subsubsection{Guardar mapa offline}

Tal i com s'ha explicat a l'apartat de \hyperlink{implm-mapfile-writer}{mapfile-writer4and} per convertir dades d'osm en format xml (.osm) o binari (.pbf) fent servir aquesta eina cal invocar-la com un intent i proporcionar un String (mitjançant els extras) amb els arguments per a osmosis, és a dir, quins plugins ha de carregar, i quins paràmetres es volen executar (en el nostre cas un fitxer d'entrada, un de sortida i algunes opcions addicionals).

\paragraph{}
Però a més d'invocar el mapfile-writer4and, l'aplicació erdapfel ha de fer més coses. A continuació es detalla el procés:

\begin{itemize}
        \item Delimitar la zona que es vol guardar.
        \item Construir una petició per l'API v0.6 de OpenStreetMap amb aquestes dades\cite{bib-osm-api-reference}.
        \item Obtenir les dades des d'internet i guardar-les localment.
        \item Invocar mapfile-writer4and per crear un fitxer .map que es pugui obrir amb erdapfel.
        \item Netejar dades temporals.
\end{itemize}

Aquests poden ser processos llargs en alguns dispositius, ja sigui per la gran capacitat de càlcul que fa servir mapfile-writer4and, com pel fet d'esperar la resposta de servidors remots per a obtenir les dades d'OpenStreetMap.

\paragraph{}
És per això que es va decidir implementar aquestes tasques de manera asíncrona en segon pla, fent servir els AsyncTasks i Threads d'Android.

\paragraph{}
La classe AsyncTask empaqueta la creació de Threads (fils d'execució) i Handlers per gestionar-los. 

\paragraph{}
Quan la tasca ha finalitzat es comunica el resultat a l'usuari i es retorna a erdapfel.

\paragraph{}
Si la operació falla (perquè mapfile-writer4and no s'ha trobat al sistema o no ha tingut prou memòria, o perquè no s'han pogut obtenir les dades d'internet) també es comunica i no es fa cap més acció.

\paragraph{}
Amb més temps s'hauria pogut buscar un mecanisme per ajudar als usuaris a acabar aquest procés de generació de mapa en els seus ordinadors personals (conservant les dades de la zona que es volia processar, per exemple). Però finalment això no es va poder fer.

\subsubsection{PolygonMode}

Activar el mode d'edició de polígons implica modificar el comportament de la pantalla principal per permetre dibuixar sobre el mapa formes poligonals.

\paragraph{}
A tal efecte, s'ha implementat una interfície simple i força intuïtiva, tot i que no perfecte.

\paragraph{}
Quan el mode d'edició està activat els ``controls'' que fins ara servien per navegar pel mapa (desplaçant-lo) o fer ``Zoom'' (amb un doble ``tap'', per exemple) es veuen alterats i passen a ser usats per a inserir nous vèrtex de polígons o modificar els vèrtexs existents (podeu veure més detalla a la \hyperlink{annex-user-man-erdapfel}{guia d'utilització del programa}).

\paragraph{}
La implementació que s'ha fet servir per aconseguir això, consisteix en capturar els events generats per l'usuari i tractar-los manualment en cas d'estar en aquest mode d'edició (sobreescribint la funció dispatchTouchEvent i evitant que l'esdeveniment es propagui a classes superiors de la jerarquia d'herència si s'està en el mode d'edició).

\paragraph{}
Això fa que el mode d'edició tingui control absolut sobre els gestos que l'usuari fa per pantalla, i inhabilita efectivament els controls ``normals'' del mapa.

\paragraph{}
Aquesta va ser la millor manera que es va trobar per permetre una edició pràctica i ``intuïtiva'' de manera senzilla.

\paragraph{}
Com a contrapartida, aquest mètode implica haver d'implementar ``manualment'' la detecció del tipus d'esdeveniment (double tap, long press, etc.), o de multi-touch, i això suposa una certa redundància, i pot arribar a comportar lleugeres diferències en el comportament i la resposta que l'usuari percep respecte la gestió d'events que s'efectua normalment al dispositiu (cosa que pot portar a certa confusió).

\paragraph{}
El mètode de mantenir estàtic el mapa mentre es dibuixa i no poder desplaçar-lo ni ampliar-lo durant la edició també pot ser problemàtic o frustrant per alguns usuaris (sobretot amb dispositius amb pantalles petites). Però a banda d'això, es poden aconseguir pintar polígons complexos de manera força intuïtiva i simple, suportant telèfons que no disposen de multi-touch, i es va considerar una implementació prou satisfactòria.

\subsubsection{MetricsMode}

La implementació dels controls del mètode de mètriques són gairebé idèntics als del d'edició de polígons, així que no els comentaré. Podeu veure amb més detall la utilització d'aquest mode de treball \hyperlink{annex-user-man-erdapfel}{aquí}.

\paragraph{}
En canvi la implementació d'aquest ``mode'' fa servir unes capacitats de la biblioteca de mapes que encara no s'han comentat, i que són interessants.

\paragraph{}
El mètode de mètriques treballa (com en el cas anterior, de fet) principalment amb coordenades de pantalla (no amb punts geogràfics).

\paragraph{}
Però per calcular distàncies aproximades és necessària la conversió de coordenades de pantalla a punts geogràfics (naturalment).

Això es realitza fent servir els mètodes ``fromPixels'' de la classe Projection (a la que es té accés, ja que cada MapView en conté una instància concreta) i el mètode ``distanceBetween'' de la classe Location (que accepta dos parells de coordenades lat/lon).

\paragraph{}
Tant els mètodes necessaris per fer aquesta transformació com els mètodes per obtenir distàncies aproximades entre dos punts geogràfics els proporciona la biblioteca de mapsforge.

\paragraph{}
Però per calcular àrees he hagut d'implementar una versió d'un algorisme de calcul d'àrees de polígons irregulars.

\paragraph{}
L'he fet basant-me en l'algorisme descrit aquí\cite{bib-polygon-area}. Aquest mètode te certes limitacions. Per començar assumeix una terra ``plana'' i sense accident geogràfics (no te en compte altituds ni la curvatura de la terra) així, per a àrees molt grans l'error acumulat pot ser notable i els resultats mostrats s'han de prendre tan sols com a aproximacions. A més tampoc mesura bé l'àrea d'un polígon intersecant.

\paragraph{}
Malgrat aquestes limitacions s'han fet algunes proves amb el càlcul d'àrees de zones geogràfiques conegudes, i els resultats són prou acceptables.

\paragraph{}
Com a petit apunt final, també s'ha implementat un senzill mecanisme de ``precisió variable'' per a mostrar les magnituds més significatives en cada moment, tant per les distàncies (que es pinten a sobre les línies) com per les àrees.

\section{Conclusió}

Finalment, per tancar aquest apartat, enunciaré breument les conclusions més rellevants que n'he extret.

\subsection{JiBX}

Sobre l'ús de l'eina JiBX com a ``parser'' de XML, he dir que no estic content d'haver-hi treballat.

\paragraph{}

Malgrat els beneficis que aquesta metodologia aportava en aquest cas concret, la manca de desenvolupament de les eines automatitzades de generació de codi i bindings va suposar un gran entrebanc pel desenvolupament d'una part clau del projecte.

\paragraph{}

A més, tot i tenir una documentació molt àmplia, complerta i ben estructurada, la gran complexitat d'aquesta eina, sumat a les dimensions dels esquemes que es volien tractar (GML en particular és d'una complexitat notable) va dificultar molt la generació ``manual'' d'aquests elements, i en definitiva va acabar causant que el resultat final fos, com a mínim, poc òptim i va convertir el parser de les biblioteques en un dels elements més inestables i propens a errors de tot el sistema.

\paragraph{}

També vaig trobar a faltar el suport de la comunitat en els meus dubtes i problemes, ja que els desenvolupadors a que vaig consultar mitjançant \hyperlink{annex-email-list-jibx}{la llista de correu} no em van ajudar a resoldre cap dels problemes que vaig patir.

\subsection{mapsforge}
\hypertarget{impl-conclusions-mapsforge}{}L'elecció del projecte mapsforge també va tenir els seus inconvenients.

\paragraph{}

En primer lloc, la documentació de mapsforge no era tant detallada com jo hauria desitjat, i en alguns casos era obsoleta.

\paragraph{}

La biblioteca contenia alguns ``bugs'' que es van haver d'anar arreglant amb pedaços mentre s'hi treballava (malgrat que la expansió de GML/KML s'estava realitzant sobre una versió ``estable'' de mapsforge (la 0.3.0)). Recordo especialment un problema amb la gestió de les ``tessel·les'' que apareixia quan s'executava el programa en la versió 4 d'Android\cite{bib-mapsforge-bug-4}.

\paragraph{}

A més l'API d'Overlays amb la que vaig treballar tenia seriosos defectes de disseny i vaig haver de fer algunes modificacions en classes d'aquesta API per tal de poder-hi treballar (cosa que a priori no hauria d'haver passat mai). Per exemple, les classes que heretaven dels ItemizedOverlays no tenien cap mena d'accés sobre les dades que aquesta classe contenia, i pràcticament només es podia mostrar, però si un cop mostrat un punt (per exemple) es volia consultar a quina posició geogràfica es trobava, això no es podia fer. És a dir, que havien implementat els mètodes ``set'' però no els ``get'' quan això no tenia cap raó de ser que jo pogués veure.

\paragraph{}

El pitjor de tot, però va ser que un cop ja s'havia implementat bona part de l'``expansió'' de KML i GML sobre aquesta API d'overlays se'm va comunicar que estava previst modificar l'API d'Overlays radicalment per a la nova versió 0.3.1 (segurament per solucionar alguns dels defecte que vaig detectar mentre hi treballava).

\paragraph{}

Això va causar certa sensació de ``desemparament'', i fa molt difícil la futura integració d'aquesta ``extensió'' de mapsforge al projecte principal, ja que implica reescriure gran part (per no dir tot) el suport de KML i GML i adaptar-lo a la nova API d'Overlays.

\paragraph{}

Quan aquest fet va tenir lloc es va decidir de continuar desenvolupant amb la versió antiga de la API més que res perquè ja estava molt avançada la implementació, però també per temes d'estabilitat.

\paragraph{}

Durant el desenvolupament d'aquest PFC també es va desplaçar el repositori de mapsforge des d'un control de versions de subversion a git, i durant el procés es va perdre totes les revisions anteriors al canvi.

\paragraph{}

Tot plegat, junt amb el poc interès que ha sostingut la proposta d'ampliació, fa que sigui poc probable que al final el treball realitzat s'integri al projecte mapsforge.


\subsection{SL4A, osmosis i treball sobre codi de tercers}

El fet d'haver hagut de modificar el codi font d'alguns d'aquest projectes (com el d'osmosis, el de SL4A o el de mapsforge) m'ha permès conèixer en primera persona els avantatges d'un bon disseny de software.

\paragraph{}

En aquest aspecte valoro molt positivament tant el projecte osmosis com el de SL4A, ja que tenen un codi molt net i clar, modular i fàcilment adaptable a les necessitats que han sorgit, i amb una documentació prou entenedors (tot i que no tant extensa com hauria requerit una assignatura d'enginyeria del software de la carrera). 

\paragraph{}

Així que ``submergir-se'' en aquests codis font no has estat tant traumàtic com esperava.

%\end{Implementation}
